package cn.honqun.tinycms.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.honqun.tinycms.common.dto.Page;
import cn.honqun.tinycms.common.exce.ApplicationException;
import cn.honqun.tinycms.constants.RegexConstants;
import cn.honqun.tinycms.constants.SecurityConstants;
import cn.honqun.tinycms.domain.copier.UserCopier;
import cn.honqun.tinycms.domain.entity.Role;
import cn.honqun.tinycms.domain.entity.User;
import cn.honqun.tinycms.domain.vo.ChangePwdVO;
import cn.honqun.tinycms.domain.vo.LoginVO;
import cn.honqun.tinycms.domain.vo.UserVO;
import cn.honqun.tinycms.repository.UserMapper;
import cn.honqun.tinycms.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "userCache")
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;

    @Override
    public User create(User user) {
        if (userMapper.isUsernameExists(user)) {
            throw new ApplicationException("用户名已经存在");
        }
        if (userMapper.isPhoneNumExists(user)) {
            throw new ApplicationException("手机号已经存在");
        }

        userMapper.create(user);
        return user;
    }

    @Override
    @CacheEvict(key = "#user.id")
    public User update(User user) {
        if (userMapper.isUsernameExists(user)) {
            throw new ApplicationException("用户名已经存在");
        }
        if (userMapper.isPhoneNumExists(user)) {
            throw new ApplicationException("手机号已经存在");
        }

        userMapper.update(user);
        return user;
    }

    @Override
    public Page<User> select(Page<User> page, UserVO userVO) {
        return userMapper.select(page, userVO);
    }

    @Override
    @CacheEvict(key = "#user.id")
    public void enabled(User user) {
        user = userMapper.selectById(user.getId());
        if (user == null) {
            throw new ApplicationException("用户不存在");
        }
        userMapper.enabled(user);
    }

    @Override
    @CacheEvict(key = "#user.id")
    public void disabled(User user) {
        user = userMapper.selectById(user.getId());
        if (user == null) {
            throw new ApplicationException("用户不存在");
        }
        if(SecurityConstants.USER_ADMIN.equals(user.getUsername())) {
            throw new ApplicationException("超级管理员角色不存在");
        }

        userMapper.disabled(user);
    }

    @Override
    @CacheEvict(key = "#changePwdVO.id")
    public void changePassword(ChangePwdVO changePwdVO) {
        userMapper.changePassword(changePwdVO);
    }

    @Override
    @Cacheable(key = "#id")
    public User selectById(Long id) {
        return userMapper.selectUserWithRoles(id);
    }

    @Override
    public User selectByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public User selectByPhoneNum(String phoneNum) {
        return userMapper.selectByPhoneNum(phoneNum);
    }

    @Override
    public List<Role> selectRoles(User user) {
        return userMapper.selectRoles(user);
    }

    @Override
    @CachePut(key = "#user.id")
    public User grantRoles(User user, List<Role> roles) {
        //首先清空以前的角色
        userMapper.clearRoles(user);
        //分配角色
        for (Role role : roles) {
            userMapper.grantRole(user, role);
        }

        return userMapper.selectUserWithRoles(user.getId());
    }


    @Override
    public UserVO login(LoginVO loginVO) {
        User user;
        //根据手机号查询
        if (Pattern.matches(RegexConstants.REGEX_PHONE_NUM, loginVO.getUsername())) {
            user = userMapper.selectByPhoneNum(loginVO.getUsername());
        } else {
            user = userMapper.selectByUsername(loginVO.getUsername());
        }

        if (user == null) {
            throw new ApplicationException(SecurityConstants.ERROR_USERNAME);
        }
        //用MySQL的加密函数加密密码（和新增用户时候的算法相同）
        String encodePassword = userMapper.encodePassword(loginVO.getPassword(), user.getPhoneNum());
        //当前用户的密码（已加密）
        String password = userMapper.selectPassword(user.getId());
        //密码错误
        if (!Objects.equals(encodePassword, password)) {
            throw new ApplicationException(SecurityConstants.ERROR_PASSWORD);
        }
        //账号禁用
        if(Boolean.FALSE.equals(user.getIsEnabled())) {
            throw new ApplicationException(SecurityConstants.ERROR_USER_DISABLED);
        }
        // sa-token登录
        StpUtil.login(user.getId(), Boolean.TRUE.equals(loginVO.getRememberMe()));
        //加载更多信息，包括用户的角色
        user = userMapper.selectById(user.getId());

        UserVO userVO = UserCopier.INSTANCE.toUserVO(user);
        //获取登录凭证
        userVO.setToken(StpUtil.getTokenValue());
        userVO.setTokenName(StpUtil.getTokenName());

        return userVO;
    }
}
